#include <iostream>
#include <string>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <csignal>

#include "timer.h"

#include "nwtcpclient.h"
#include "nwtcpserver.h"
#include "nwudpclient.h"
#include "nwudpserver.h"


static bool gs_bRunningStatus = true;

static void onSigInt(int signum)
{
    signal(signum, SIG_DFL); // 还原默认的信号处理
    gs_bRunningStatus = false;
    //printf("Runing status: %d.\r\n", gs_bRunningStatus);
    return;
}

void tcpclientTest()
{
    NetworkUtil::ConnectionConfigInfo stCfg(false, true, "127.0.0.1", 60000, 10001, 1024);
    NetworkUtil::TcpClient client(stCfg);

    client.setRecvCallbackFunc([&client](const std::string& strDataInfo){
        std::cout << "local receive [" << client.remoteInfo() << "] data: " << strDataInfo << std::endl;
    });

    client.init();
#if 0
    std::this_thread::sleep_for(std::chrono::seconds(1));
    client.deinit();
    client.deinit();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    client.init();
#endif
    int index = 0;
    while (gs_bRunningStatus)
    {
        //std::cout << "Running..." << std::endl;
        std::string strData = std::string("this is test data, index ") + std::to_string(++index);
        client.write(strData); // ok
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#if 0
        std::string strReadData = "";
        client.read(strReadData); // ok
        std::cout << "local receive [" << client.remoteInfo() << "] data: " << strReadData << std::endl;
#endif
    }

    std::cout << "exiting..." << std::endl;
    client.deinit();

    return;
}

void tcpserverTest()
{
    NetworkUtil::ConnectionConfigInfo stCfg(false, false, "0.0.0.0", 0, 60000, 1024);
    NetworkUtil::TcpServer server(stCfg);

    int index = 0;
    NetworkUtil::setRecvCallbackFunc([&index](const std::string& strDataInfo, NetworkUtil::Session* pSession){
        if (pSession)
        {
            std::cout << "local receive [" << pSession->remoteInfo() << "] data: " << strDataInfo << std::endl;

            std::string strData = std::string("server have recv your data, index ") + std::to_string(++index);
            pSession->write(strData); // ok
        }
    });

    server.init();

    while (gs_bRunningStatus)
    {
        //std::cout << "Running..." << std::endl;
        std::this_thread::yield();
    }

    server.deinit();

    return;
}

void udpserverTest()
{
    NetworkUtil::ConnectionConfigInfo stCfg(false, false, "0.0.0.0", 0, 60000, 1024);
    NetworkUtil::UdpServer server(stCfg);

    int index = 0;
    server.setRecvCallbackFunc([&server, &index](const std::string& strDataInfo, const asio::ip::udp::endpoint& objSenderEndPoint){
        std::cout << "local receive [" << server.remoteInfo(objSenderEndPoint) << "] data: " << strDataInfo << std::endl;

        std::string strData = std::string("server have recv your data, index ") + std::to_string(++index);
        server.write(strData, objSenderEndPoint); // ok
    });

    server.init();
    //server.deinit();
    //server.deinit();

    //server.init();

    while (gs_bRunningStatus)
    {
        //std::cout << "Running..." << std::endl;
        std::this_thread::yield();
    }

    server.deinit();

    return;
}

void udpclientTest()
{
    NetworkUtil::ConnectionConfigInfo stCfg(false, false, "127.0.0.1", 60000, 10001, 1024);
    NetworkUtil::UdpClient client(stCfg);

    client.setRecvCallbackFunc([&client](const std::string& strDataInfo){
        std::cout << "local receive [" << client.remoteInfo() << "] data: " << strDataInfo << std::endl;
    });

    client.init();
    //client.deinit();
    //client.deinit();

    //client.init();

    int index = 0;
    while (gs_bRunningStatus)
    {
        //std::cout << "Running..." << std::endl;
        std::string strData = std::string("this is test data, index ") + std::to_string(++index);
        client.write(strData); // ok
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#if 0
        std::string strReadData = "";
        client.read(strReadData); // ok
        std::cout << "local receive [" << client.remoteInfo() << "] data: " << strReadData << std::endl;
#endif
    }

    client.deinit();

    return;
}

int main(int argc, char** argv)
{
    signal(SIGINT, onSigInt);

    int type = 0;
    if (argc >= 2)
    {
        if (0 == strcmp(argv[1], "ts"))
        {
            type = 1;
        }
        else if (0 == strcmp(argv[1], "tc"))
        {
            type = 2;
        }
        else if (0 == strcmp(argv[1], "us"))
        {
            type = 3;
        }
        else if (0 == strcmp(argv[1], "uc"))
        {
            type = 4;
        }
    }

    std::cout << "Starting, running in mode: " << type << std::endl;

    switch (type)
    {
    case 1:
    {
        tcpserverTest();
        break;
    }
    case 2:
    {
        tcpclientTest();
        break;
    }
    case 3:
    {
        udpserverTest();
        break;
    }
    case 4:
    {
        udpclientTest();
        break;
    }
    }

    std::cout << "Stoping..." << std::endl;

    return 0;
}
